/**
 * 讯飞语音识别前端交互脚本
 */
document.addEventListener('DOMContentLoaded', function() {
    // DOM元素
    const micButton = document.getElementById('mic-button');
    const micText = micButton.querySelector('.mic-text');
    const systemAudioButton = document.getElementById('system-audio-button');
    const systemAudioText = systemAudioButton.querySelector('.system-audio-text');
    const switchLangButton = document.getElementById('switch-lang-button');
    const switchLangText = switchLangButton.querySelector('.switch-lang-text');
    const statusIndicator = document.getElementById('status-indicator');
    
    // 语言标签元素
    const sourceLangEl = document.getElementById('source-lang');
    const targetLangEl = document.getElementById('target-lang');
    
    // 语音识别结果元素
    const finalResult = document.getElementById('final-result');
    const tempResult = document.getElementById('temp-result');
    
    // 翻译结果元素
    const finalTranslation = document.getElementById('final-translation');
    const tempTranslation = document.getElementById('temp-translation');
    
    // 调试信息元素
    const audioStatusEl = document.getElementById('audio-status');
    const wsStatusEl = document.getElementById('ws-status');
    const sampleRateEl = document.getElementById('sample-rate');
    const audioSourceEl = document.getElementById('audio-source');
    const translationDirectionEl = document.getElementById('translation-direction');
    
    // WebSocket连接
    let socket = null;
    // 录音状态
    let isRecording = false;
    // 当前音频源类型
    let currentAudioSource = 'none'; // 'mic' 或 'system' 或 'none'
    // 当前翻译方向
    let currentTranslationDirection = 'cn2en'; // 'cn2en' 或 'en2cn'
    
    // 音频处理相关变量
    let mediaRecorder = null;
    let audioContext = null;
    let mediaStream = null;
    let processor = null;
    
    // 重连计数器
    let reconnectAttempts = 0;
    const MAX_RECONNECT_ATTEMPTS = 3;
    
    // 初始化事件监听
    micButton.addEventListener('click', () => toggleRecording('mic'));
    systemAudioButton.addEventListener('click', () => toggleRecording('system'));
    switchLangButton.addEventListener('click', toggleTranslationDirection);
    
    // 更新调试信息
    function updateDebugInfo() {
        // 更新WebSocket状态
        if (!socket) {
            wsStatusEl.textContent = `WebSocket状态: 未连接`;
        } else {
            const states = ['正在连接', '已连接', '正在关闭', '已关闭'];
            wsStatusEl.textContent = `WebSocket状态: ${states[socket.readyState]}`;
        }
        
        // 更新音频状态
        if (!audioContext) {
            audioStatusEl.textContent = `音频状态: 未初始化`;
        } else {
            audioStatusEl.textContent = `音频状态: ${audioContext.state}`;
        }
        
        // 更新采样率
        if (audioContext) {
            sampleRateEl.textContent = `采样率: ${audioContext.sampleRate} Hz`;
        } else {
            sampleRateEl.textContent = `采样率: 未知`;
        }
        
        // 更新音频源
        audioSourceEl.textContent = `音频源: ${currentAudioSource === 'mic' ? '麦克风' : 
                                    currentAudioSource === 'system' ? '系统音频' : '无'}`;
                                    
        // 更新翻译方向
        translationDirectionEl.textContent = `翻译方向: ${currentTranslationDirection === 'cn2en' ? '中译英' : '英译中'}`;
    }
    
    // 定期更新调试信息
    setInterval(updateDebugInfo, 1000);
    
    /**
     * 切换翻译方向
     */
    function toggleTranslationDirection() {
        // 如果正在录音，先停止录音
        if (isRecording) {
            stopRecording();
        }
        
        // 切换方向
        if (currentTranslationDirection === 'cn2en') {
            // 切换为英译中
            currentTranslationDirection = 'en2cn';
            switchLangText.textContent = '英译中';
            sourceLangEl.textContent = '英文';
            targetLangEl.textContent = '中文';
        } else {
            // 切换为中译英
            currentTranslationDirection = 'cn2en';
            switchLangText.textContent = '中译英';
            sourceLangEl.textContent = '中文';
            targetLangEl.textContent = '英文';
        }
        
        // 清空结果区域
        finalResult.textContent = '';
        tempResult.textContent = '';
        finalTranslation.textContent = '';
        tempTranslation.textContent = '';
        
        // 向服务器发送切换方向的消息
        if (socket && socket.readyState === WebSocket.OPEN) {
            socket.send(JSON.stringify({
                action: 'switchDirection',
                direction: currentTranslationDirection
            }));
        }
        
        // 更新调试信息
        translationDirectionEl.textContent = `翻译方向: ${currentTranslationDirection === 'cn2en' ? '中译英' : '英译中'}`;
    }
    
    /**
     * 切换录音状态
     * @param {string} source - 音频源类型：'mic'表示麦克风，'system'表示系统音频
     */
    function toggleRecording(source) {
        if (isRecording) {
            // 如果当前正在录制的不是请求的源，则先停止当前录制，然后开始新的录制
            if (currentAudioSource !== source) {
                stopRecording();
                setTimeout(() => startRecording(source), 500);
            } else {
                stopRecording();
            }
        } else {
            startRecording(source);
        }
    }
    
    /**
     * 开始录音
     * @param {string} source - 音频源类型：'mic'表示麦克风，'system'表示系统音频
     */
    function startRecording(source) {
        // 重置重连计数器
        reconnectAttempts = 0;
        
        // 更新UI状态
        isRecording = true;
        currentAudioSource = source;
        
        // 更新按钮状态
        if (source === 'mic') {
            micButton.classList.add('recording');
            micText.textContent = '点击停止录音';
            systemAudioButton.classList.remove('recording');
            systemAudioText.textContent = '电脑音频';
        } else {
            systemAudioButton.classList.add('recording');
            systemAudioText.textContent = '点击停止录音';
            micButton.classList.remove('recording');
            micText.textContent = '点击开始录音';
        }
        
        // 清空结果区域
        finalResult.textContent = '';
        tempResult.textContent = '';
        finalTranslation.textContent = '';
        tempTranslation.textContent = '';
        
        // 更新音频源显示
        audioSourceEl.textContent = `音频源: ${source === 'mic' ? '麦克风' : '系统音频'}`;
        audioStatusEl.textContent = '音频状态: 正在请求权限...';
        
        // 根据不同的音频源类型请求权限
        if (source === 'mic') {
            // 请求麦克风权限
            navigator.mediaDevices.getUserMedia({ 
                audio: {
                    echoCancellation: true,
                    noiseSuppression: true,
                    autoGainControl: true
                }, 
                video: false 
            })
            .then(handleMediaStream)
            .catch(handleMediaError);
        } else {
            // 请求系统音频权限
            navigator.mediaDevices.getDisplayMedia({ 
                video: true,
                audio: true
            })
            .then(handleMediaStream)
            .catch(handleMediaError);
        }
    }
    
    /**
     * 处理媒体流
     */
    function handleMediaStream(stream) {
        mediaStream = stream;
        
        // 检查是否有音频轨道
        const audioTracks = stream.getAudioTracks();
        if (audioTracks.length === 0 && currentAudioSource === 'system') {
            showError('未检测到系统音频，请确保勾选"共享系统音频"选项');
            stopRecording();
            return;
        }
        
        audioStatusEl.textContent = `音频状态: 已获取${currentAudioSource === 'mic' ? '麦克风' : '系统音频'}权限`;
        
        // 创建WebSocket连接
        connectWebSocket();
        
        // 等待WebSocket连接建立后再开始处理音频
        setTimeout(() => {
            if (socket && socket.readyState === WebSocket.OPEN) {
                setupAudioProcessing(stream);
            } else {
                showError('WebSocket连接失败，无法开始录音');
                stopRecording();
            }
        }, 500);
    }
    
    /**
     * 处理媒体错误
     */
    function handleMediaError(err) {
        console.error(`获取${currentAudioSource === 'mic' ? '麦克风' : '系统音频'}失败:`, err);
        showError(`无法访问${currentAudioSource === 'mic' ? '麦克风' : '系统音频'}，请确保已授予权限`);
        isRecording = false;
        
        // 重置按钮状态
        micButton.classList.remove('recording');
        micText.textContent = '点击开始录音';
        systemAudioButton.classList.remove('recording');
        systemAudioText.textContent = '电脑音频';
        
        currentAudioSource = 'none';
        audioStatusEl.textContent = `音频状态: ${currentAudioSource === 'mic' ? '麦克风' : '系统音频'}访问被拒绝`;
    }
    
    /**
     * 设置音频处理
     */
    function setupAudioProcessing(stream) {
        try {
            // 创建音频上下文
            audioContext = new (window.AudioContext || window.webkitAudioContext)({
                sampleRate: 16000 // 强制使用16kHz采样率
            });
            
            // 如果是系统音频，可能需要处理视频轨道
            if (currentAudioSource === 'system') {
                // 停止视频轨道，我们只需要音频
                const videoTracks = stream.getVideoTracks();
                videoTracks.forEach(track => {
                    if (track.kind === 'video') {
                        track.enabled = false; // 禁用视频轨道但不移除，以保持流活跃
                    }
                });
            }
            
            const source = audioContext.createMediaStreamSource(stream);
            
            // 创建重采样处理器 - 减小缓冲区大小提高实时性
            const bufferSize = 2048; // 从4096减小到2048
            processor = audioContext.createScriptProcessor(bufferSize, 1, 1);
            
            // 音频数据处理计数器
            let processCounter = 0;
            let lastSendTime = 0;
            let accumulatedSilence = 0;
            
            // 处理音频数据
            processor.onaudioprocess = function(e) {
                if (socket && socket.readyState === WebSocket.OPEN && isRecording) {
                    // 获取音频数据
                    const inputData = e.inputBuffer.getChannelData(0);
                    
                    // 检查是否有声音（避免发送静音数据）
                    const volume = calculateVolume(inputData);
                    
                    // 音频活动检测
                    const isSilent = volume < 0.005;
                    if (isSilent) {
                        accumulatedSilence++;
                    } else {
                        accumulatedSilence = 0;
                    }
                    
                    // 控制发送频率
                    processCounter++;
                    const now = Date.now();
                    const timeSinceLastSend = now - lastSendTime;
                    
                    // 说话时每帧都发送，静音时降低发送频率
                    const shouldSend = !isSilent || (isSilent && accumulatedSilence % 3 === 0);
                    
                    // 确保发送间隔合理
                    if (shouldSend && (timeSinceLastSend > 20)) {
                        // 转换为16bit PCM
                        const pcmData = convertFloatTo16BitPCM(inputData);
                        
                        // 发送音频数据
                        try {
                            socket.send(pcmData);
                            lastSendTime = now;
                            
                            // 添加调试日志（每100个数据包记录一次）
                            if (Math.random() < 0.01) {
                                console.log(`发送音频数据: ${inputData.length} 采样点, 音量: ${volume.toFixed(4)}, 静音: ${isSilent}`);
                            }
                        } catch (err) {
                            console.error('发送音频数据失败:', err);
                            // 如果WebSocket已关闭，尝试重新连接
                            if (socket.readyState !== WebSocket.OPEN && reconnectAttempts < MAX_RECONNECT_ATTEMPTS) {
                                reconnectWebSocket();
                            }
                        }
                    }
                }
            };
            
            // 连接节点
            source.connect(processor);
            processor.connect(audioContext.destination);
            
            console.log(`音频处理已启动 - 采样率: ${audioContext.sampleRate}Hz, 缓冲区大小: ${bufferSize}`);
            audioStatusEl.textContent = `音频状态: 已启动 (${audioContext.state})`;
            sampleRateEl.textContent = `采样率: ${audioContext.sampleRate} Hz`;
        } catch (error) {
            console.error('设置音频处理失败:', error);
            showError('设置音频处理失败: ' + error.message);
            stopRecording();
        }
    }
    
    /**
     * 计算音频音量
     */
    function calculateVolume(buffer) {
        let sum = 0;
        // 计算平均振幅
        for (let i = 0; i < buffer.length; i++) {
            sum += Math.abs(buffer[i]);
        }
        return sum / buffer.length;
    }
    
    /**
     * 将Float32音频数据转换为16bit PCM
     */
    function convertFloatTo16BitPCM(float32Array) {
        const length = float32Array.length;
        const buffer = new ArrayBuffer(length * 2);
        const view = new DataView(buffer);
        
        for (let i = 0; i < length; i++) {
            // 将-1.0 ~ 1.0的浮点值转换为-32768 ~ 32767的整数
            const s = Math.max(-1, Math.min(1, float32Array[i]));
            const val = s < 0 ? s * 0x8000 : s * 0x7FFF;
            view.setInt16(i * 2, val, true); // true表示小端字节序
        }
        
        return buffer;
    }
    
    /**
     * 停止录音
     */
    function stopRecording() {
        // 更新UI状态
        isRecording = false;
        micButton.classList.remove('recording');
        micText.textContent = '点击开始录音';
        systemAudioButton.classList.remove('recording');
        systemAudioText.textContent = '电脑音频';
        
        // 停止音频处理
        if (processor) {
            try {
                processor.disconnect();
            } catch (e) {
                console.error('断开处理器连接失败:', e);
            }
            processor = null;
        }
        
        if (audioContext) {
            try {
                audioContext.close().catch(console.error);
            } catch (e) {
                console.error('关闭音频上下文失败:', e);
            }
            audioContext = null;
        }
        
        // 停止媒体流
        if (mediaStream) {
            try {
                mediaStream.getTracks().forEach(track => track.stop());
            } catch (e) {
                console.error('停止媒体轨道失败:', e);
            }
            mediaStream = null;
        }
        
        // 更新状态
        currentAudioSource = 'none';
        audioStatusEl.textContent = '音频状态: 已停止';
        audioSourceEl.textContent = '音频源: 无';
        
        // 关闭WebSocket连接
        closeWebSocket();
    }
    
    /**
     * 关闭WebSocket连接
     */
    function closeWebSocket() {
        if (socket) {
            try {
                if (socket.readyState === WebSocket.OPEN) {
                    // 发送停止录音命令
                    socket.send(JSON.stringify({ action: 'stop' }));
                    // 延迟关闭连接，确保最后的结果能够接收
                    setTimeout(() => {
                        try {
                            socket.close();
                        } catch (e) {
                            console.error('关闭WebSocket失败:', e);
                        }
                        socket = null;
                        statusIndicator.classList.remove('active');
                        wsStatusEl.textContent = 'WebSocket状态: 已关闭';
                    }, 1000);
                } else {
                    socket = null;
                    statusIndicator.classList.remove('active');
                    wsStatusEl.textContent = 'WebSocket状态: 已关闭';
                }
            } catch (e) {
                console.error('关闭WebSocket时出错:', e);
                socket = null;
                statusIndicator.classList.remove('active');
                wsStatusEl.textContent = 'WebSocket状态: 关闭出错';
            }
        }
    }
    
    /**
     * 尝试重新连接WebSocket
     */
    function reconnectWebSocket() {
        reconnectAttempts++;
        console.log(`尝试重新连接WebSocket (${reconnectAttempts}/${MAX_RECONNECT_ATTEMPTS})...`);
        
        closeWebSocket();
        setTimeout(() => {
            if (isRecording) {
                connectWebSocket();
            }
        }, 1000);
    }
    
    /**
     * 建立WebSocket连接
     */
    function connectWebSocket() {
        // 获取当前页面协议
        const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
        // 构建WebSocket URL
        const wsUrl = `${protocol}//${window.location.host}/speech-ws`;
        
        wsStatusEl.textContent = 'WebSocket状态: 正在连接...';
        
        try {
            // 设置WebSocket二进制类型为ArrayBuffer，提高传输效率
            socket = new WebSocket(wsUrl);
            socket.binaryType = 'arraybuffer';
            
            // 连接建立时
            socket.onopen = function() {
                console.log('WebSocket连接已建立');
                statusIndicator.classList.add('active');
                wsStatusEl.textContent = 'WebSocket状态: 已连接';
                
                // 发送开始录音命令
                socket.send(JSON.stringify({ action: 'start' }));
                
                // 发送当前翻译方向
                socket.send(JSON.stringify({
                    action: 'switchDirection',
                    direction: currentTranslationDirection
                }));
            };
            
            // 接收消息时
            socket.onmessage = function(event) {
                try {
                    const response = JSON.parse(event.data);
                    handleRecognitionResult(response);
                } catch (e) {
                    console.error('解析WebSocket消息失败:', e, event.data);
                }
            };
            
            // 连接关闭时
            socket.onclose = function(event) {
                console.log('WebSocket连接已关闭', event.code, event.reason);
                statusIndicator.classList.remove('active');
                wsStatusEl.textContent = `WebSocket状态: 已关闭 (${event.code})`;
                
                // 如果仍处于录音状态，尝试重新连接
                if (isRecording && reconnectAttempts < MAX_RECONNECT_ATTEMPTS) {
                    reconnectWebSocket();
                } else if (isRecording) {
                    showError('WebSocket连接已断开，无法继续录音');
                    stopRecording();
                }
            };
            
            // 连接错误时
            socket.onerror = function(error) {
                console.error('WebSocket错误:', error);
                statusIndicator.classList.remove('active');
                statusIndicator.classList.add('error');
                wsStatusEl.textContent = 'WebSocket状态: 连接错误';
                
                showError('连接服务器失败，请稍后重试');
                
                if (isRecording && reconnectAttempts < MAX_RECONNECT_ATTEMPTS) {
                    reconnectWebSocket();
                } else if (isRecording) {
                    stopRecording();
                }
            };
            
        } catch (error) {
            console.error('创建WebSocket连接失败:', error);
            wsStatusEl.textContent = 'WebSocket状态: 创建失败';
            showError('无法连接到语音识别服务');
            stopRecording();
        }
    }
    
    /**
     * 处理识别结果
     */
    function handleRecognitionResult(response) {
        if (response.error) {
            showError(response.error);
            return;
        }
        
        // 根据返回的结果类型更新UI
        if (response.type === 'final') {
            // 最终识别结果
            finalResult.textContent += response.text;
            tempResult.textContent = '';
            
            // 自动滚动到底部
            const resultContainer = document.getElementById('result-container');
            resultContainer.scrollTop = resultContainer.scrollHeight;
        } else if (response.type === 'interim') {
            // 中间识别结果
            tempResult.textContent = response.text;
        } else if (response.type === 'final-translation') {
            // 最终翻译结果
            finalTranslation.textContent += response.text;
            tempTranslation.textContent = '';
            
            // 自动滚动到底部
            const translationContainer = document.getElementById('translation-container');
            translationContainer.scrollTop = translationContainer.scrollHeight;
        } else if (response.type === 'interim-translation') {
            // 中间翻译结果
            tempTranslation.textContent = response.text;
        } else if (response.type === 'system') {
            // 系统消息
            console.log('系统消息:', response.text);
        }
    }
    
    /**
     * 显示错误信息
     */
    function showError(message) {
        tempResult.textContent = `错误: ${message}`;
        statusIndicator.classList.add('error');
        console.error('错误:', message);
        
        // 3秒后清除错误状态
        setTimeout(() => {
            statusIndicator.classList.remove('error');
        }, 3000);
    }
    
    // 初始化调试信息
    updateDebugInfo();
}); 